﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Administration;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SAE.Common
{
    /// <summary>
    /// PropertyHelper
    /// </summary>
    public class PropertyHelper
    {
        public static string LogFileDirectoryPath = AppDomain.CurrentDomain.BaseDirectory + "Logs\\";

        /// <summary>
        /// Imports the specified file name.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="siteUrl">The site URL.</param>
        public static void Import(string fileName,string siteUrl)
        {   
            string logFileName = LogFileDirectoryPath + DateTime.Now.ToString("yyyy-MM-dd-hh-mm") + ".txt";

            try
            {
                using (SPSite site = new SPSite(siteUrl))
                {
                    ServerContext context = ServerContext.GetContext(site);

                    UserProfileManager profileManager = new UserProfileManager(context);

                    PropertyCollection pc = profileManager.PropertiesWithSection;

                    XmlDocument xDoc = new XmlDocument();
                    xDoc.Load(fileName);

                    foreach (XmlNode section in xDoc.SelectNodes("properties//section"))
                    {
                        Property prop = null;
                        //add sections
                        //string sectionName = GetAttributeValue(section, "Name");
                        //Property prop = pc.GetPropertyByName(sectionName);

                        //if (prop == null)
                        //{
                        //    prop = pc.Create(false);
                        //    prop.Name = sectionName;
                        //}

                        //prop.DisplayName = GetAttributeValue(section, "DisplayName");

                        //prop.Commit();

                        //add properties
                        foreach (XmlNode property in section.SelectNodes("property"))
                        {
                            string name = GetAttributeValue(property, "Name").TrimEnd();

                            try
                            {
                                prop = pc.GetPropertyByName(name);

                                string value = string.Empty;

                                if (prop == null)
                                {
                                    prop = pc.Create(false);
                                    prop.Name = name;

                                    value = GetAttributeValue(property, "Type").TrimEnd();

                                    if (value.Length > 0)
                                    {
                                        prop.Type = value;
                                    }

                                    value = GetAttributeValue(property, "Length").TrimEnd();

                                    if (value.Length > 0)
                                    {
                                        prop.Length = int.Parse(value);
                                    }

                                    //fix some exist problems
                                    if (prop.Length > 3600)
                                    {
                                        prop.Length = 3600;
                                    }

                                    value = GetAttributeValue(property, "UserOverridePrivacy").TrimEnd();

                                    if (value.Length > 0)
                                    {
                                        prop.UserOverridePrivacy = bool.Parse(value);
                                    }

                                    value = GetAttributeValue(property, "IsMultivalued").TrimEnd();

                                    if (value.Length > 0)
                                    {
                                        prop.IsMultivalued = bool.Parse(value);
                                    }
                                }

                                value = GetAttributeValue(property, "DisplayName").TrimEnd();

                                if (value.Length > 0)
                                {
                                    prop.DisplayName = value;
                                }

                                value = GetAttributeValue(property, "PrivacyPolicy").TrimEnd();

                                if (value.Length > 0)
                                {
                                    if (value.ToLower() == "optin")
                                    {
                                        prop.PrivacyPolicy = PrivacyPolicy.OptIn;
                                    }
                                }

                                value = GetAttributeValue(property, "DefaultPrivacy").TrimEnd();

                                if (value.Length > 0)
                                {
                                    if (value.ToLower() == "public")
                                    {
                                        prop.DefaultPrivacy = Privacy.Public;
                                    }

                                    if (value.ToLower() == "private")
                                    {
                                        prop.DefaultPrivacy = Privacy.Private;
                                    }
                                }

                                value = GetAttributeValue(property, "IsUserEditable").TrimEnd();

                                if (value.Length > 0)
                                {
                                    prop.IsUserEditable = bool.Parse(value);
                                }

                                value = GetAttributeValue(property, "IsVisibleOnEditor").TrimEnd();

                                if (value.Length > 0)
                                {
                                    prop.IsVisibleOnEditor = bool.Parse(value);
                                }

                                value = GetAttributeValue(property, "IsVisibleOnViewer").TrimEnd();

                                if (value.Length > 0)
                                {
                                    prop.IsVisibleOnViewer = bool.Parse(value);
                                }

                                value = GetAttributeValue(property, "ChoiceType").TrimEnd();

                                if (value.Length > 0)
                                {
                                    if (value.ToLower() == "closed")
                                    {
                                        prop.ChoiceType = ChoiceTypes.Closed;
                                    }
                                }

                                value = GetAttributeValue(property, "ChoiceList").TrimEnd();

                                if (value.Length > 0)
                                {
                                    foreach (string item in prop.ChoiceList.GetAllTerms(false))
                                    {
                                        prop.ChoiceList.Remove(item);
                                    }

                                    foreach (string item in value.Split(new char[] { ',' }))
                                    {
                                        if (item.Trim().Length > 0)
                                        {
                                            prop.ChoiceList.Add(item);
                                        }
                                    }
                                }

                                prop.Commit();

                                 Common.LogUtility.AppendLog(logFileName, "Save property [" + name + "] succeeded.");
                            }
                            catch (Exception ex)
                            {
                                 Common.LogUtility.AppendLog(logFileName, "########################################" + Environment.NewLine + "\t\t\tSave Property [" + name + "] failed, error message: \"" + ex.Message + "\"" + Environment.NewLine + "\t\t\t########################################");
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                 Common.LogUtility.AppendLog(logFileName, ": General error occured, error message:" + ex.Message);
            }
        }

        /// <summary>
        /// Gets the attribute value.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <returns></returns>
        private static string GetAttributeValue(XmlNode property, string attributeName)
        {
            if (property.Attributes[attributeName] != null)
            {
                return property.Attributes[attributeName].Value;
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Exports the specified site URL.
        /// </summary>
        /// <param name="siteUrl">The site URL.</param>
        /// <param name="fileName">Name of the file.</param>
        public static void Export(string siteUrl,string fileName)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                ServerContext context = ServerContext.GetContext(site);

                Microsoft.Office.Server.UserProfiles.UserProfileManager profileManager = new Microsoft.Office.Server.UserProfiles.UserProfileManager(context);

                XmlDocument propertyDocument = new XmlDocument();

                //
                XmlNode rootNode=propertyDocument.CreateElement("properties");
                propertyDocument.AppendChild(rootNode);

                XmlNode sectionNode = null;
                XmlNode childNode = null;

                foreach (Microsoft.Office.Server.UserProfiles.Property prop in profileManager.PropertiesWithSection)
                {
                    if (prop.IsSection)
                    {
                        sectionNode = propertyDocument.CreateElement("section");

                        SetAttribute(propertyDocument, sectionNode, "Name", prop.Name);

                        rootNode.AppendChild(sectionNode);
                    }
                    else
                    {
                        childNode = propertyDocument.CreateElement("property");

                        SetAttribute(propertyDocument,childNode, "Name", prop.Name);
                        SetAttribute(propertyDocument, childNode, "DisplayName", prop.DisplayName);
                        SetAttribute(propertyDocument, childNode, "Type", prop.Type);
                        SetAttribute(propertyDocument, childNode, "Length", prop.Length);
                        SetAttribute(propertyDocument, childNode, "PrivacyPolicy", prop.PrivacyPolicy);
                        SetAttribute(propertyDocument, childNode, "DefaultPrivacy", prop.DefaultPrivacy);
                        SetAttribute(propertyDocument, childNode, "UserOverridePivacy", prop.UserOverridePrivacy);
                        SetAttribute(propertyDocument, childNode, "IsUserEditable", prop.IsUserEditable);
                        SetAttribute(propertyDocument, childNode, "IsVisibleOnEditor", prop.IsVisibleOnEditor);
                        SetAttribute(propertyDocument, childNode, "IsVisibleOnViewer", prop.IsVisibleOnViewer);
                        SetAttribute(propertyDocument,childNode,  "IsMultivalued",prop.IsMultivalued);
                        SetAttribute(propertyDocument,childNode,  "ChoiceType",prop.ChoiceType);

                        string choiceList = string.Empty;
                        if (prop.ChoiceList != null)
                        {
                            string[] list = prop.ChoiceList.GetAllTerms(true);

                            foreach (string item in list)
                            {
                                choiceList += item + ",";
                            }

                            choiceList = choiceList.TrimEnd(',');
                        }
                        SetAttribute(propertyDocument, childNode, "ChoiceList", choiceList);

                        SetAttribute(propertyDocument,childNode,  "Order",prop.DisplayOrder);

                        sectionNode.AppendChild(childNode);
                    }
                }

                propertyDocument.Save(fileName);
            }
        }

        /// <summary>
        /// Sets the attribute.
        /// </summary>
        /// <param name="propertyDocument">The property document.</param>
        /// <param name="node">The node.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <param name="attributeValue">The attribute value.</param>
        private static void SetAttribute(XmlDocument propertyDocument,XmlNode node, string attributeName, object attributeValue)
        {
            if (node.Attributes[attributeName] != null)
            {
                node.Attributes[attributeName].Value = attributeValue==null?string.Empty:attributeValue.ToString();
            }
            else
            {
                XmlAttribute attr = propertyDocument.CreateAttribute(attributeName);
                attr.Value = attributeValue == null ? string.Empty : attributeValue.ToString();
                node.Attributes.Append(attr);
            }
        }
    }
}
